iconEuler Examples

d'Hondt and Hare-Niemeyer

The file hondt.e contains an implementation of the d'Hondt and the Hare-Niemeyer procedures for elections.

Euler File

>load hondt;

Let us start with a simple example. Assume the votes are the following.

>v=[24,27,5]
[24,  27,  5]

Now we have 10 seats. How would distribute these seats?

The d'Hondt method does the following.

>hondt(v,10)
[4,  5,  1]

The result of the Hare-Niemeyer method is the same in this case.

>hnbest(v,10)
[4,  5,  1]

Explanation - d'Hondt

The d'Hondt method divides the seats by 1, 2, 3, ... and sorts the results. Then it takes the highest n numbers to determine the seats.

Let us simulate that. First we divide all elements of v by 1 to 10 and put that into one vector.

>k=10; vh=redim(v/(1:k)',1,k*3)
[24,  27,  5,  12,  13.5,  2.5,  8,  9,  1.66667,  6,  6.75,  1.25,
4.8,  5.4,  1,  4,  4.5,  0.833333,  3.42857,  3.85714,  0.714286,  3,
3.375,  0.625,  2.66667,  3,  0.555556,  2.4,  2.7,  0.5]

Here are the numbers of the parties for each entry of vh.

>ph=redim(dup(1:3,k),1,k*3)
[1,  2,  3,  1,  2,  3,  1,  2,  3,  1,  2,  3,  1,  2,  3,  1,  2,  3,
1,  2,  3,  1,  2,  3,  1,  2,  3,  1,  2,  3]

Now we sort vh in descending order.

>{vhs,is}=sort(-vh); -vhs
[27,  24,  13.5,  12,  9,  8,  6.75,  6,  5.4,  5,  4.8,  4.5,  4,
3.85714,  3.42857,  3.375,  3,  3,  2.7,  2.66667,  2.5,  2.4,
1.66667,  1.25,  1,  0.833333,  0.714286,  0.625,  0.555556,  0.5]

The parties which these numbers belong to, are the following.

>ph[is]
[2,  1,  2,  1,  2,  1,  2,  1,  2,  3,  1,  2,  1,  2,  1,  2,  2,  1,
2,  1,  3,  1,  3,  3,  3,  3,  3,  3,  3,  3]

We now take the first 10 values of the vector, determine the parties of these indices, and count the number of times a party occurs.

>is=is[1:10], ps=ph[is], getmultiplicities(1:3,ps)
[2,  1,  5,  4,  8,  7,  11,  10,  14,  3]
[2,  1,  2,  1,  2,  1,  2,  1,  2,  3]
[4,  5,  1]

Explanation - Hare Niemeyer

Hare-Niemeyer works with a different, and less obscure trick. First we determine the fractional number of seats each party should get.

>s=v/sum(v)*10
[4.28571,  4.82143,  0.892857]

This is of course not possible. Therefore, we give the parties the integer part of this, thus

dHondt and Hare-Niemeyer

>sp=floor(s)
[4,  4,  0]

We have 2 seats left. Now we determine the errors for each party and add 1 seat for the highest 2 errors.

>s-sp, {h,i}=sort(s-sp); i=i[-2:-1],
[0.285714,  0.821429,  0.892857]
[2,  3]

Party 2 and 3 have the largest error. So we reduct this error the most, if we add one seat to 2 and 3.

>sp[i]=sp[i]+1; sp,
[4,  5,  1]

Checking the Results

For a comparison, we assume two parties, where one gets p percent of the votes, and k seats. Then we can write a function for the number of seats the party gets.

>function map shondt (p) := hondt([p,1-p],k)[1]

Now we can plot the number of seats the party gets versus the number of seats it should get (in red).

>k=10; plot2d("k*x",0,1,color=red); ...
 plot2d("shondt",>add):

dHondt and Hare-Niemeyer

This tends to put the smaller party at a disadvantage.

Let us try the same with Hare-Niemeyer.

>function map shn (p) := hnbest([p,1-p],k)[1]; ...
 k=10; plot2d("k*x",0,1,color=red); ...
 plot2d("shn",>add):

dHondt and Hare-Niemeyer

This clearly looks much better. In fact, it rounds the fractional number of seats to the next integer.

We can do the same for three parties with an equal share of votes for the other two.

>function map shondt (p) := hondt([p,1-p/2,1-p/2],k)[1]; ...
 k=10; plot2d("k*x/2",0,1,color=red); ...
 plot2d("shondt",>add):

dHondt and Hare-Niemeyer

>function map shn (p) := hnbest([p,1-p/2,1-p/2],k)[1]; ...
 k=10; plot2d("k*x/2",0,1,color=red); ...
 plot2d("shn",>add):

dHondt and Hare-Niemeyer

Again the small party clearly gets a fair share.

Examples